/*
 -- IOTA Crypto Core
 --
 -- 2018 by Thomas Pototschnig <microengineer18@gmail.com>
 -- discord: pmaxuw#8292
 -- https://gitlab.com/iccfpga-rv
 --
 -- Permission is hereby granted, free of charge, to any person obtaining
 -- a copy of this software and associated documentation files (the
 -- "Software"), to deal in the Software without restriction, including
 -- without limitation the rights to use, copy, modify, merge, publish,
 -- distribute, sublicense, and/or sell copies of the Software, and to
 -- permit persons to whom the Software is furnished to do so, subject to
 -- the following conditions:
 --
 -- The above copyright notice and this permission notice shall be
 -- included in all copies or substantial portions of the Software.
 --
 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 -- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 -- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 -- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWAR
 */


#include "xparameters.h"        // Project memory and device map
#include "xgpio.h"              // Xilinx GPIO routines
#include "gpio/gpio.h"

XGpio Gpio_LEDs; /* The driver instance for the IIC GPIO */

namespace GPIO {
	namespace {
		uint32_t shadow;
		uint32_t shadow_dir;
		uint32_t shadow_af;
	}

	int gpio_init() {
		// Define local variables
		int status;
		/*
		 * Initialize the GPIO driver so that it's ready to use,
		 * specify the device ID that is generated in xparameters.h
		 */
		status = XGpio_Initialize(&Gpio_LEDs, XPAR_AXI_GPIO_0_DEVICE_ID);
		if (status != XST_SUCCESS) {
			return XST_FAILURE;
		}
		XGpio_SetDataDirection(&Gpio_LEDs, 1, 0xffffffff);
		XGpio_SetDataDirection(&Gpio_LEDs, 2, 0x00000000);
		XGpio_DiscreteWrite(&Gpio_LEDs, 2, 0x00000000);

	//	XGpio_DiscreteWrite(&Gpio_LEDs, 1, 0x0);
		shadow = 0x00000000;
		shadow_dir = 0x00000000;
		shadow_af = 0x00000000;
		return XST_SUCCESS;
	}

	void setBit(int bit) {
		shadow |= bit;
		XGpio_DiscreteWrite(&Gpio_LEDs, 1, shadow);   // Set LEDs
	}

	void clrBit(int bit) {
		shadow &= ~bit;
		XGpio_DiscreteWrite(&Gpio_LEDs, 1, shadow);   // Set LEDs
	}

	/*int readBit(int bit) {
		return !!(XGpio_DiscreteRead(&Gpio_LEDs, 2) & bit);
	}*/

	uint32_t read() {
		return XGpio_DiscreteRead(&Gpio_LEDs, 1);
	}

	void setDir(int bit, int state) {
		if (state)
			shadow_dir &= ~bit;
		else
			shadow_dir |= bit;
		XGpio_SetDataDirection(&Gpio_LEDs, 1, shadow_dir);

	}

	void setAF(int bit, int state) {
		if (state)
			shadow_af |= bit;
		else
			shadow_af &= ~bit;
		XGpio_DiscreteWrite(&Gpio_LEDs, 2, shadow_af);

	}

}

